             package com.java.diagnostics.visualizer.recommender.memory;
             
             import com.java.diagnostics.visualizer.data.AggregateData;
             import com.java.diagnostics.visualizer.data.DataPoint;
             import com.java.diagnostics.visualizer.data.TupleData;
             import com.java.diagnostics.visualizer.parser.vgc.constants.HiddenVGCLabels;
             import com.java.diagnostics.visualizer.recommender.Recommendation;
             import com.java.diagnostics.visualizer.recommender.RecommendationBase;
             import com.java.diagnostics.visualizer.recommender.util.RecommendationLabels;
             
             public class LookForMemoryLeak
               extends RecommendationBase
               implements Recommendation
             {
               public void recommend(AggregateData data)
               {
                 if (isIBM(data)) {
                   Object gcMode = getGCMode(data);
                   if (!"balanced".equals(gcMode)) {
                     TupleData amountFreed = data
                       .getTupleData(HiddenVGCLabels.ROLLING_AVERAGE_AMOUNT_FREED);
                     TupleData usedHeap = data
                       .getTupleData(HiddenVGCLabels.ROLLING_AVERAGE_HEAP_AFTER_GLOBAL);
                     if (usedHeap == null) {
                       usedHeap = 
                         data.getTupleData(HiddenVGCLabels.ROLLING_AVERAGE_HEAP_AFTER_GC);
                     }
                     
                     if ((amountFreed != null) && (!amountFreed.isEmpty()) && 
                       (usedHeap != null) && (!usedHeap.isEmpty()))
                     {
                       int tupleLength = Math.min(amountFreed.length(), 
                         usedHeap.length());
                       
                       if (tupleLength < 100) {
                         return;
                       }
                       int start = tupleLength / 3;
                       
                       DataPoint[] amountFreedPoints = amountFreed.getDataPoints();
                       
                       for (int i = start; i < tupleLength - 50; i++) {
                         DataPoint amountFreedOne = amountFreedPoints[i];
                         DataPoint amountFreedTwo = amountFreedPoints[(i + 50)];
                         
                         double changeInAmountFreed = (amountFreedOne.getRawY() - 
                           amountFreedTwo.getRawY()) / (
                           amountFreedOne.getRawX() - 
                           amountFreedTwo.getRawX());
                         
                         DataPoint usedHeapOne = usedHeap
                           .getDataPoint(amountFreedOne.getSequenceUID());
                         DataPoint usedHeapTwo = usedHeap
                           .getDataPoint(amountFreedTwo.getSequenceUID());
                         
                         if ((usedHeapOne != null) && (usedHeapTwo != null)) {
                           double changeInUsedHeap = (usedHeapOne.getRawY() - 
                             usedHeapTwo.getRawY()) / (
                             usedHeapOne.getRawX() - 
                             usedHeapTwo.getRawX());
                           if ((changeInUsedHeap > 0.0D) && 
                             (changeInUsedHeap - changeInAmountFreed > 0.2D)) {
                             addProblem(
                               data, 
                               RecommendationLabels.APPLICATION_LEAKING);
                             return;
                           }
                         }
                       }
                     }
                   }
                 }
               }
             }


